package org.simplextensions.registry.phaselisteners;

import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.AnnotationMemberValue;
import javassist.bytecode.annotation.ArrayMemberValue;
import javassist.bytecode.annotation.MemberValue;
import org.simplextensions.annotations.Properties;
import org.simplextensions.registry.*;
import org.simplextensions.scanner.ClassScannerHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;

public class PropertiesScanPhaseListener extends PhaseListenerAdapter implements ISimpleXtensionsClassScanner {

	private static final Logger log = LoggerFactory.getLogger(PropertiesScanPhaseListener.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.simplextensions.scanner.IScanPhaseListener#scanClass(javassist
	 * .bytecode.ClassFile, javassist.bytecode.annotation.Annotation)
	 */
	public void scanClass(SimpleXtensionsBundle bundle, String className, Annotation a) {
		ArrayMemberValue properties = null;
		if (Properties.class.getCanonicalName().equals(a.getTypeName())) {
			properties = (ArrayMemberValue) a.getMemberValue("value");

			ExtensionPoint ep = bundle.getExtensionRegistry().getExtensionPointMD(className);
			if (ep != null)
				setProperty(ep, properties);

			for (Extension e : bundle.getExtensionRegistry().getExtensionsMDByClass(className)) {
				setProperty(e, properties);
			}

		} else if (org.simplextensions.annotations.Extension.class.getCanonicalName().equals(a.getTypeName())) {
			properties = (ArrayMemberValue) a.getMemberValue("properties");
			String extensionId = ClassScannerHelper.getStringValue(a, "id");
			Collection<Extension> extensionsByClass = bundle.getExtensionRegistry().getExtensionsMDByClass(className);
			for (Extension e : extensionsByClass) {
				if (e.getId().equals(extensionId))
					setProperty(e, properties);
			}
		} else if (org.simplextensions.annotations.ExtensionPoint.class.getCanonicalName().equals(a.getTypeName())) {
			properties = (ArrayMemberValue) a.getMemberValue("properties");
			String extensionPointId = ClassScannerHelper.getStringValue(a, "id");
			setProperty(bundle.getExtensionRegistry().getExtensionPointMD(extensionPointId), properties);
		}

	}

	/**
	 * @param ep
	 * @param properties
	 */
	private void setProperty(ConfigurableElem ep, ArrayMemberValue properties) {
		if (properties == null)
			return;

		log.info("setting properties of " + ep.getId());
		MemberValue[] value = properties.getValue();
		for (MemberValue mv : value) {
			AnnotationMemberValue amv = (AnnotationMemberValue) mv;
			Annotation property = amv.getValue();
			String smvName = ClassScannerHelper.getStringValue(property, "name");
			String smv = ClassScannerHelper.getStringValue(property, "stringValue");
			Integer imv = ClassScannerHelper.getIntegerValue(property, "intValue");
			Long lmv = ClassScannerHelper.getLongValue(property, "longValue");
			Boolean bmv = ClassScannerHelper.getBooleanValue(property, "boolValue");
			Class<?> cmv = ClassScannerHelper.getClassValue(property, "classValue");

			PropertyValue propertyValue = new PropertyValue(smv, imv, lmv, bmv, cmv);

			log.info("setting property value: " + smvName + " of " + ep.getClassName());

			ep.setPropertyValue(smvName, propertyValue);
		}
	}

}